<?php

namespace pmvc\data;

use pmvc\data\AbstractDataSource;
use pmvc\util\StringUtil;
use Exception;

class MysqlDataSource 
	extends AbstractDataSource {

	public $port;
	public $clientFlags;
	public $host;
	public $username;
	public $password;
	public $database;
	
	private $link = FALSE;
	
	private function get_last_error() {
		return "errno ".mysql_errno()." - ".mysql_error();
	}

	public function createTransaction() {
		return new MysqlTransaction($this);
	}

	public function connect() {
		if ($this->link!==FALSE) {
			return;
		}
		if (empty($this->port)) {
			$this->port = "3306";
		}
		if (empty($this->clientFlags)) {
			$this->clientFlags = 0;
		}
		$this->link = mysql_connect(
			$this->host.":".$this->port,
			$this->username,
			$this->password,
			TRUE,
			$this->clientFlags);
		if ($this->link===FALSE) {
			throw new Exception(
				"Connection failed: ".$this->get_last_error());
		}
		if (mysql_select_db($this->database, $this->link)===FALSE) {
			throw new Exception(
				"Selecting database failed: ".$this->get_last_error());
		}
	}
	
	public function escape($str) {
		return mysql_escape_string($str);
	}
	
	public function query() {
		$a		= func_get_args();
        $sql 	= array_shift($a);
        $sql 	= $this->buildQuery($sql, $a);
        \pmvc\log\Log::debug("Executing query: {0}", $sql);
        $ret = mysql_query($sql, $this->link);
        if ($ret===FALSE) {
			throw new Exception(
				"Query failed: ".$this->get_last_error());
        }
        return $ret;
	}
	
	public function update() {
		$a		= func_get_args();
        $sql 	= array_shift($a);
        $sql 	= $this->buildQuery($sql, $a);
        \pmvc\log\Log::debug("Executing update: {0}", $sql);
        $ret = mysql_query($sql, $this->link);
        if ($ret===FALSE) {
			throw new Exception(
				"Query failed: ".$this->get_last_error());
        }
        return $ret;
	}
	
	public function lastInsertId() {
		$ret = mysql_insert_id($this->link);
        if ($ret===FALSE) {
			throw new Exception(
				"Getting insert id failed: ".$this->get_last_error());
        }
        return $ret;
	}
	
	public function querySingle() {
		$a = func_get_args();
        $res = call_user_func_array(array($this,"query"), $a);
        $ret = $this->numberOfRows($res)>0 
        	? $this->fetchRowObject($res)
        	: FALSE;
        $this->freeResult($res);
        return $ret;
	}
	
	public function queryMultiple() {
		$a = func_get_args();
        $res = call_user_func_array(array($this,"query"), $a);
        $ret = $this->numberOfRows($res)>0 
        	? $this->fetchRowObjects($res)
        	: Array();
        $this->freeResult($res);
        return $ret;
	}
	
	public function numberOfRows($res) {
		$ret = mysql_num_rows($res);
        if ($ret===FALSE) {
			throw new Exception(
				"Getting number of rows failed: ".$this->get_last_error());
        }
        return $ret;
	}
	
	public function fetchRowObject($res) {
		return mysql_fetch_object($res);
	}
	
	public function numberOfRowsAffectedRows($res) {
		return mysql_affected_rows($res);
	}
	
	public function fetchRowObjects($res) {
		$objs = Array();
		while (($obj = $this->fetchRowObject($res))!==FALSE) {
			$objs[] = $obj;
		}
		return $objs;
	}
	
	public function freeResult($res) {
		$ret = mysql_free_result($res);
        if ($ret===FALSE) {
			throw new Exception(
				"Freeing result failed: ".$this->get_last_error());
        }
        return $ret;
	}

}

?>